#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <queue>
#include <stack>
#include <algorithm>
#include <string>
#include <map>
#include <set>
#include <vector>
#include <ctime>

using namespace std;

#define BEGINS(x) namespace x {
#define ENDS(x) } // end of namespace x

BEGINS(test1)

class Animal {
public:
    void run() {
        cout << "I don't know how to run" << endl;
        return ;
    };

};

class Cat : public Animal {
public:
    void run() {
        cout << "I can run with four legs" << endl;
        return ;
    }
};

int main() {
    Cat a;
    Animal &b = a;
    Animal *c = &a;
    a.run(); // I can run with four legs
    b.run(); // I don't know how to run
    c->run(); // I don't know how to run
    return 0;
}

ENDS(test1)

BEGINS(test2)

class Animal {
public:
    virtual void run() {
        cout << "I don't know how to run" << endl;
        return ;
    };
    virtual void foo() {
        cout << "foo function" << endl;
        return ;
    }
};

class Cat : public Animal {
public:
    void run() override { // override 不保证功能性
        cout << "I can run with four legs" << endl;
        return ;
    }
    /*void f00() override {
        cout << "f00 function" << endl;
        return ;
    };*/
};

int main() {
    Cat a;
    Animal &b = a;
    Animal *c = &a;
    a.run(); // I can run with four legs
    b.run(); // I can run with four legs
    c->run(); // I can run with four legs
    return 0;
}

ENDS(test2)

BEGINS(test3)

class Animal {
public:
    virtual void run() {
        cout << "I don't know how to run" << endl;
        return ;
    };

};

class Cat : public Animal {
public:
    void run() override { // override 不保证功能性
        cout << "I can run with four legs" << endl;
        return ;
    }
};

class People : public Animal {
public:
    void run() override {
        cout << "I can run with two legs" << endl;
        return ;
    }
};

class Bird : public Animal {
public:
    void run() override {
        cout << "I can fly" << endl;
        return ;
    }
};

int main() {
    srand(time(0));
    Animal *arr[10];
    for (int i = 0; i < 10; i++) {
        switch (rand() % 3) {
            case 0: arr[i] = new Cat(); break;
            case 1: arr[i] = new People(); break;
            case 2: arr[i] = new Bird(); break;
        }
    }
    for (int i = 0; i < 10; ++i) {
        arr[i]->run();
    }
    return 0;
}

ENDS(test3)

BEGINS(test4)

// 如果基类析构函数不是虚函数的话，子类可能没有办法正确析构。
class Animal {
public:
    virtual void run() {
        cout << "I don't know how to run" << endl;
        return ;
    };
    virtual ~Animal() {
        cout << "Animal destructor" << endl;
    }
};

class Cat : public Animal {
public:
    void run() override { // override 不保证功能性
        cout << "I can run with four legs" << endl;
        return ;
    }
    ~Cat() override {
        cout << "Cat destructor" << endl;
    }
};

class People : public Animal {
public:
    void run() override {
        cout << "I can run with two legs" << endl;
        return ;
    }
    ~People() override {
        cout << "People destructor" << endl;
    }
};

class Bird : public Animal {
public:
    void run() override {
        cout << "I can fly" << endl;
        return ;
    }
    ~Bird() override {
        cout << "Bird destructor" << endl;
    }
};

int main(){
    srand(time(0));
    Animal *p;
    switch(rand() % 3) {
        case 0: p = new Cat(); break;
        case 1: p = new People(); break;
        case 2: p = new Bird(); break;
    }
    p->run();
    delete p;
    return 0;
}

ENDS(test4)

BEGINS(test5)

class Animal {
public:
    virtual void run() = 0; // 纯虚函数
};

class Cat : public Animal {
public:
    void run() override { // override 不保证功能性
        cout << "I can run with four legs" << endl;
        return ;
    }
};

int main() {
    Cat a;
    Animal &b = a;
    Animal *c = &a;
    a.run(); // I can run with four legs
    b.run(); // I can run with four legs
    c->run(); // I can run with four legs
    return 0;
}

ENDS(test5)


int main() {
//    test1::main();
//    test2::main();
//    test3::main();
//    test4::main();
    test5::main();
    return 0;
}